/*
 * =====================================================================================
 *
 *       Filename:  SmartPtr.cpp
 *
 *    Description:
 *
 *        Version:  1.0
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Yt (fndisme), fndisme@163.com
 *   Organization:
 *
 * =====================================================================================
 */
#include <memory>
#include <iostream>
static void interfaceOfSharedPtr();
int main() {
	interfaceOfSharedPtr();

}

class Object {
 public:
  Object(int id) : m_id(id) { std::cout << "init obj " << m_id << std::endl; }
  ~Object() { std::cout << "bye bye " << m_id << std::endl; }
	int id() const { return m_id;}
private:
	int m_id;
};

	typedef std::shared_ptr<Object> ObjectPtr;

void deleterOfObject(Object* obj) {
	if(obj)
		std::cout << "delete obj " << obj->id() << std::endl;
	delete obj;
}

void print(ObjectPtr obj) {
  std::cout << "count " << obj.use_count() << " id " << obj->id() << std::endl;
}

void printRef(const ObjectPtr& obj) {
  std::cout << "ref count " << obj.use_count() << " id " << obj->id()
            << std::endl;
}


void interfaceOfSharedPtr() {
	ObjectPtr obj(new Object(1));
	std::cout << "ref count is " << obj.use_count() << std::endl;
	ObjectPtr obj2(obj);
	std::cout << "ref count is " << obj.use_count() << std::endl;
	ObjectPtr obj3 = obj;
	std::cout << "ref count is " << obj.use_count() << std::endl;

	obj2.reset(); // reset means what?
	std::cout << "ref count is " << obj.use_count() << std::endl;

	ObjectPtr obj4;
	obj3.swap(obj4);
	std::cout << "ref count is " << obj.use_count() << std::endl;

	auto p = obj.get();
	if(p) {
		std::cout << "id is " << p->id() << std::endl;
	}

	if(obj) { // operator bool
		std::cout << "p id is " << obj->id() << std::endl;
		std::cout << "ref id is " << (*obj).id() << std::endl;
	}

	obj4 = nullptr;
	std::cout << "only one hold ptr " << obj.unique() << std::endl;
	print(obj);
	printRef(obj);
}

void useDeleter() {
	ObjectPtr obj(new Object(2), deleterOfObject);
	ObjectPtr obj2 = obj;
}

